/**
 * 
 */
package com.aspire.android.heliar.pub;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;

import com.aspire.android.heliar.Heliar;
import com.aspire.android.heliar.activities.PubListActivity;
import com.aspire.android.heliar.pub.storage.PubStorageManager;
import com.aspire.android.heliar.pub.storage.SQLitePubStorageManager;
import com.aspire.android.heliar.raw.RawDataFilter;
import com.aspire.android.heliar.raw.RawDataManager;
import com.aspire.android.heliar.raw.mms.MMS;
import com.aspire.android.heliar.raw.mms.MMSDataManager;
import com.aspire.android.heliar.utils.ContextFactory;
import com.aspire.android.heliar.utils.FileSystem;

/**
 * @author panglei
 * 
 */

public class PubManager {

	public static final String RAW_DATA_MANAGER_MMS = "mmsRawDataManager";

	private List<Pub> pubs = new LinkedList<Pub>();
	private Map<String, Pub> pubsMap = new LinkedHashMap<String, Pub>();

	private String[] whiteAddresses = new String[] { "10658000" };

	// PubStorageManager
	private PubStorageManager pubStorageManager = new SQLitePubStorageManager(
			ContextFactory.getInstance());

	// RawDataManager manager
	private Map<String, RawDataManager<?>> managers = new HashMap<String, RawDataManager<?>>();

	private void initRawDataManager() {
		managers.put(RAW_DATA_MANAGER_MMS, new MMSDataManager());
	}

	/**
	 * 载入本地以存储的Pub数据
	 */
	public void loadLocalStorePubs() {
		pubs.clear();
		pubsMap.clear();

		List<Pub> pubs = pubStorageManager.listPubs();
		for (Pub pub : pubs) {
			String coverPath = getPubCoverFilepathByCoverId(pub.getCoverId());
			if (coverPath != null) {
				pub.setCoverFilepath(coverPath);
			}
			this.pubs.add(pub);
			this.pubsMap.put(pub.getKey(), pub);
		}
	}

	public String getPubCoverFilepathByCoverId(long id) {
		PubAttachment attachment = pubStorageManager.getPubAttachment((int) id);
		if (attachment != null) {
			return attachment.getFilepath();
		}
		return null;
	}

	/**
	 * 同步数据到Pub
	 */
	public void syncRawDataToPub() {

		boolean isRefresh = false;

		Set<String> managerNames = managers.keySet();
		for (String managerName : managerNames) {
			if (managerName.equals(RAW_DATA_MANAGER_MMS)) {
				@SuppressWarnings("unchecked")
				RawDataManager<MMS> manager = (RawDataManager<MMS>) managers
						.get(managerName);
				List<MMS> mmss = manager.list(new RawDataFilter<MMS>() {

					@Override
					public boolean filter(MMS mms) {
						for (String address : whiteAddresses) {
							if (!address.equals(mms.getAddress())) {
								return false;
							}
						}
						return true;
					}

				});

				// Sync MMS to Pub
				for (MMS mms : mmss) {
					String key = manager.generatePubId(mms);
					if (!pubsMap.containsKey(key)) {
						// Load full mms
						mms = manager.get(String.valueOf(mms.getId()));
						Pub pub = manager.toPub(mms);
						if (pub != null) {
							storePub(pub);
							isRefresh = true;
						}
					}
				}

			}
		}

		// Refresh list
		if (isRefresh) {
			loadLocalStorePubs();
		}
	}

	public void deletePub(Pub pub, boolean isSyncRawData) {
		List<PubAttachment> pubAttachments = pubStorageManager
				.listPubAttachmentsByPubId(pub.getId());
		Log.d(Heliar.LOG_TAG, "pub.getId() = " + pub.getId()
				+ " pubAttachments size = " + pubAttachments.size());
		for (PubAttachment pubAttachment : pubAttachments) {
			File file = new File(pubAttachment.getFilepath());
			if (file.exists()) {
				Log.d(Heliar.LOG_TAG, "delete file:" + file.getAbsolutePath());
				FileSystem.delete(file);
			}
		}

		pubStorageManager.deletetPubAttachmentsByPubId(pub.getId());
		pubStorageManager.deleteContentNodesByPubId(pub.getId());
		pubStorageManager.deletePub(pub.getId());

		if (isSyncRawData) {
			Set<String> managerNames = managers.keySet();
			for (String managerName : managerNames) {
				if (managerName.equals(RAW_DATA_MANAGER_MMS)) {
					@SuppressWarnings("unchecked")
					RawDataManager<MMS> manager = (RawDataManager<MMS>) managers
							.get(managerName);
					manager.delete(pub.getRawId());
				}
			}
		}

		this.pubs.remove(pub);
		this.pubsMap.remove(pub.getKey());
	}

	/**
	 * 存储Pub
	 * 
	 * @param pub
	 * @return
	 */
	private long storePub(Pub pub) {
		long pubId = -1;
		if (pub != null) {

			long coverId = 0;
			if (pub.getCover() != null) {
				coverId = storePubCover(pub.getCover());
			}
			pub.setCoverId(coverId);

			pubId = pubStorageManager.insertPub(pub);
			ContentNode rootNode = pub.getRootNode();
			rootNode.setPubId(pubId);
			rootNode.setParentId(0);

			PubAttachment pubAttachment = pubStorageManager
					.getPubAttachment(coverId);

			if (pubAttachment != null) {
				pubAttachment.setPubId(pubId);
				pubStorageManager.updatePubAttachment(coverId, pubAttachment);
			}

			storeContentNode(pubId, rootNode);
		}
		return pubId;
	}

	//
	private void storeContentNode(long pubId, ContentNode contentNode) {
		long parentId = pubStorageManager.insertContentNode(contentNode);

		for (PubAttachment pubAttachment : contentNode.getAttachments()) {
			storeAttachment(contentNode.getPubId(), parentId, pubAttachment);
		}

		for (ContentNode childNode : contentNode.getChildNodes()) {
			childNode.setPubId(pubId);
			childNode.setParentId(parentId);
			storeContentNode(pubId, childNode);
		}

	}

	private long storePubCover(ImageAttachment pubAttachment) {
		String filename = null;
		if (pubAttachment.getContentType().equals(
				PubAttachment.CONTENT_TYPE_IMAGE_JPEG)) {

			filename = writeBitmapToFile(Bitmap.createScaledBitmap(
					pubAttachment.getBitmap(), PubListActivity.PUB_IMAGE_WIDTH,
					PubListActivity.PUB_IMAGE_HEIGHT, false),
					Bitmap.CompressFormat.JPEG, ".jpg");

		} else if (pubAttachment.getContentType().equals(
				PubAttachment.CONTENT_TYPE_IMAGE_GIF)) {

			filename = writeBitmapToFile(Bitmap.createScaledBitmap(
					pubAttachment.getBitmap(), PubListActivity.PUB_IMAGE_WIDTH,
					PubListActivity.PUB_IMAGE_HEIGHT, false),
					Bitmap.CompressFormat.JPEG, ".jpg");
		}

		pubAttachment.setFilepath(filename);
		pubAttachment.setContentNodeId(0);
		pubAttachment.setPubId(0);

		return pubStorageManager.insertPubAttachment(pubAttachment);
	}

	private void storeAttachment(long pubId, long contentNodeId,
			PubAttachment pubAttachment) {
		String filename = null;
		if (pubAttachment.getContentType().equals(
				PubAttachment.CONTENT_TYPE_IMAGE_JPEG)) {
			ImageAttachment imageAttachment = (ImageAttachment) pubAttachment;
			filename = writeBitmapToFile(imageAttachment.getBitmap(),
					Bitmap.CompressFormat.JPEG, ".jpg");
		} else if (pubAttachment.getContentType().equals(
				PubAttachment.CONTENT_TYPE_IMAGE_GIF)) {
			ImageAttachment imageAttachment = (ImageAttachment) pubAttachment;
			filename = writeBitmapToFile(imageAttachment.getBitmap(),
					Bitmap.CompressFormat.JPEG, ".jpg");

		} else if (pubAttachment.getContentType().equals(
				PubAttachment.CONTENT_TYPE_SOUND_MIDI)) {

		} else if (pubAttachment.getContentType().equals(
				PubAttachment.CONTENT_TYPE_SOUND_AMR)) {

		}

		pubAttachment.setFilepath(filename);
		pubAttachment.setContentNodeId(contentNodeId);
		pubAttachment.setPubId(pubId);

		Log.d(Heliar.LOG_TAG,
				"pubAttachment.getContentType:"
						+ pubAttachment.getContentType());

		pubStorageManager.insertPubAttachment(pubAttachment);
	}

	private String writeBitmapToFile(Bitmap bitmap,
			Bitmap.CompressFormat format, String extensionName) {

		if (bitmap == null) {
			return null;
		}

		String filename = System.currentTimeMillis() + extensionName;

		File rootDir = new File(Environment.getExternalStorageDirectory(),
				PubStorageManager.ROOT_PATH);
		if (!rootDir.exists()) {
			rootDir.mkdir();
		}

		File file = new File(rootDir, filename);
		try {
			FileOutputStream out = new FileOutputStream(file);
			bitmap.compress(format, 90, out);

		} catch (FileNotFoundException e) {
			Log.e(Heliar.LOG_TAG, e.getMessage(), e);
		}

		return file.getAbsolutePath();

	}

	public List<Pub> getPubList() {
		return pubs;
	}

	public Pub getPub(int index) {
		if (index >= 0 && index < pubs.size()) {
			Pub pub = pubs.get(index);
			List<ContentNode> rootChildNodes = pubStorageManager
					.listContentNodes(pub.getId(), 0);
			if (rootChildNodes.size() > 0) {
				ContentNode rootNode = rootChildNodes.get(0);
				rootNode = getContentNode(rootNode);
				pub.setRootNode(rootNode);
			}
			return pub;
		}
		return null;
	}

	private ContentNode getContentNode(ContentNode parentContentNode) {

		if (parentContentNode != null) {
			List<PubAttachment> pubAttachments = getPubAttachment(parentContentNode
					.getId());
			parentContentNode.setAttachments(pubAttachments);

			List<ContentNode> childContentNodes = pubStorageManager
					.listContentNodes(parentContentNode.getPubId(),
							parentContentNode.getId());

			if (childContentNodes.size() > 0) {
				for (ContentNode childContentNode : childContentNodes) {
					getContentNode(childContentNode);
				}
				parentContentNode.setChildNodes(childContentNodes);
			}
		}

		return parentContentNode;
	}

	private List<PubAttachment> getPubAttachment(long contentNodeId) {
		return pubStorageManager.listPubAttachments(contentNodeId);
	}

	/**
	 * Singleton
	 */
	private static PubManager instance = null;

	private PubManager() {
		initRawDataManager();
	}

	public static synchronized PubManager getInstance() {
		if (instance == null) {
			instance = new PubManager();
		}
		return instance;
	}
}
